package com.system.core.message.iospush;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.system.core.message.iospush.dto.APSMessage;
import com.system.core.message.iospush.dto.Aps;
import com.system.core.message.iospush.dto.ApsPushEventSource;
import com.system.core.view.common.response.CommonResponse;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Slf4j
public class MessagePushService {
	
	private final ApnsConfig apnsConfig;
	private final Environment environment;
	
	@Async
	@EventListener
	public CommonResponse apnsPush(ApsPushEventSource req) {
		APSMessage msg = APSMessage.builder().aps(
				Aps.builder().alert(req.getType().getMessage()).build()
			).notifyType(req.getType().getCode()).build();
		return apnsPush(req.getWalletAddress(),null,msg);
	}

	/**
	 * 推送官方文档：https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns
	 * @param walletAddress
	 * @param msg
	 * @return
	 */
	public CommonResponse apnsPush(String deviceToken,String messageId, APSMessage msg) {
		
		
		Boolean isProduct = false;
		String[] envs = environment.getActiveProfiles();
		if(envs[0].equalsIgnoreCase("prod")) {
			isProduct = true;
		}
		
		
		String apnsId=StringUtils.isBlank(messageId)?UUID.randomUUID().toString():messageId;
		
		HttpClient client = HttpClient.newBuilder().build();
		try {
			String jsonMsg = JSONObject.toJSONString(msg);
			String apiUrl = "https://" + (isProduct ? apnsConfig.getProductServer() : apnsConfig.getSandboxServer()) +"/3/device/" + deviceToken;
			log.debug("[ans]发送内容：{}，通过API URL：{}，apnsConfig:{}",jsonMsg,apiUrl,apnsConfig.toString());
			HttpRequest request = HttpRequest.newBuilder()
					.uri(URI.create(apiUrl)) // deviceToken 从手机上获取到的设备 token
					// 发送的消息内容
					.POST(BodyPublishers.ofString(jsonMsg))
					// 请苹果接口的令牌，通过 JWT 生成，有时间有过期（好像是一个小时过期，所以不要去缓存它，每次请求时去重新生成一个就好）
					.setHeader("authorization", "bearer "+APNSToken.getToken(apnsConfig.getTeamid(),apnsConfig.getKeyid(),apnsConfig.getSecret()))
					// 可以理解成APP名称吧，符合格式即可，随意命名
					.setHeader("apns-id", apnsId)
					// 消息的提示方式，alert 是指弹出横幅
					.setHeader("apns-push-type", "alert")
					.setHeader("apns-expiration", "0")
					// 10 表示立即发送
					.setHeader("apns-priority", "10")
					// APPID，和证书一致
					.setHeader("apns-topic", apnsConfig.getAppid())
					.build();
	 
			HttpResponse<?> response = client.send(request, HttpResponse.BodyHandlers.ofString());
			// 返回状态码，如果是 200 则表示发送成功
			Integer statuCode = response.statusCode();
			 
			if (statuCode == null || statuCode.intValue() != 200) {
				log.error("apns发送失败，加入失败处理队列，失败内容是：{}",response.body());
				
				return CommonResponse.buildFailureResult(response.body().toString());
			} else {
				log.info("apns苹果返回状态：{}，发送给：{}，内容：{}",statuCode.intValue(),deviceToken,response.body());
			}
		} catch (Exception e) {
			e.printStackTrace();
			return CommonResponse.buildFailureResult(e);
		}
		
		return CommonResponse.buildSuccessResult("success");
	}
	
}